/**
  ************************************* Copyright ******************************
  * FileName   : iic.c
  * Version    : v1.0
  * Author     : yychao
  * Date       : 2023-01-18
  * Description:
  * Function List:
  	1. ....
  	   <version>:
  <modify staff>:
  		  <data>:
   <description>:
  	2. ...
  ******************************************************************************
 */
#include "iic.h"
#include "systick.h"
#include "tim_delay.h"

#define GPIO_SCL GPIOB
#define GPIO_SDA GPIOB
#define GPIO_SCL_PIN GPIO_PIN_8
#define GPIO_SDA_PIN GPIO_PIN_9

#define SDA_H	(GPIO_SDA->PBSC = GPIO_SDA_PIN)
#define SDA_L	(GPIO_SDA->PBC = GPIO_SDA_PIN)
#define SCL_H	(GPIO_SCL->PBSC = GPIO_SCL_PIN)
#define SCL_L	(GPIO_SCL->PBC = GPIO_SCL_PIN)
#define SDA_READ	(GPIO_ReadInputDataBit(GPIO_SDA, GPIO_SDA_PIN))

//#define delay_us	(SysTick_Delay_Us)

void SDA_IN(void)
{
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE);

    GPIO_InitType GPIO_InitStructure = { 0 };
    GPIO_InitStructure.Pin        = GPIO_SDA_PIN;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitPeripheral(GPIO_SDA, &GPIO_InitStructure);
}

void SDA_OUT(void)
{
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE);

    GPIO_InitType GPIO_InitStructure = { 0 };
    GPIO_InitStructure.Pin        = GPIO_SDA_PIN;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitPeripheral(GPIO_SDA, &GPIO_InitStructure);
}

void SCL_OUT(void)
{
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE);

    GPIO_InitType GPIO_InitStructure = { 0 };
    GPIO_InitStructure.Pin        = GPIO_SCL_PIN;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitPeripheral(GPIO_SCL, &GPIO_InitStructure);
}

void iic_init(void)
{
    SDA_OUT();
    SCL_OUT();
}
void iic_start(void)
{
    SDA_OUT();
    SDA_H;
    SCL_H;
    delay_us(2);
    SDA_L;
    delay_us(2);
    SCL_L;
    return;
}

void iic_stop(void)
{
    SDA_OUT();
    SDA_L;
    SCL_L;
    delay_us(2);
    SCL_H;
    delay_us(2);
    SDA_H;
    delay_us(2);
    SCL_L;
    return;
}
void iic_wait_ack(void)
{
    uint8_t errtmie = 0;
    SDA_IN();
    SDA_H;
    delay_us(2);
    SCL_H;
    delay_us(2);
    while (SDA_READ) {
        errtmie++;
        if (errtmie >= 0xff) {
            iic_stop();
            return;
        }
    }
    SCL_L;
    return;
}
void iic_ack(void)
{
    SDA_OUT();
    SDA_L;
    SCL_L;
    delay_us(2);
    SCL_H;
    delay_us(5);
    SCL_L;
    return;
}
void iic_nack(void)
{
    SDA_OUT();
    SDA_H;
    SCL_L;
    delay_us(2);
    SCL_H;
    delay_us(5);
    SCL_L;
    return;
}
void iic_send_byte(uint8_t byte_data)
{
    uint8_t i = 8;
    SDA_OUT();
    SCL_L;
    delay_us(2);
    for (i = 0; i <8; i++) {
        if((byte_data & 0x80) >> 7) {
            SDA_H;
        } else {
            SDA_L;
        }
        byte_data <<= 1;
        delay_us(2);
        SCL_H;
        delay_us(2);
        SCL_L;
        delay_us(2);
    }
}
uint8_t iic_read_byte(uint8_t ack)
{
    uint8_t recv = 0;
    SDA_IN();
    for(uint8_t i = 0; i < 8; i++) {
        SCL_L;
        delay_us(2);
        SCL_H;
        recv <<= 1;
        if(SDA_READ) {
            recv++;
        }
        delay_us(2);
    }
    if(ack == 0) {
        iic_nack();
    } else {
        iic_ack();
    }
}